package top.korori.task;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import top.korori.common.enums.IsDel;
import top.korori.sv.entity.*;
import top.korori.sv.entity.vo.SvUserAreaTreeVo;
import top.korori.sv.mapper.SvWorkLikeMapper;
import top.korori.sv.mapper.SvWorkStarMapper;
import top.korori.sv.service.*;
import top.korori.utils.GenImage;
import top.korori.utils.GenUserName;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Component
@Slf4j
@AllArgsConstructor
public class GenDataTask {

    private final SvUserService svUserService;

    private final SvUserAreaService svUserAreaService;

    private final SvWorkService svWorkService;

    private final SvWorkLikeMapper svWorkLikeMapper;

    private final SvWorkStarMapper svWorkStarMapper;

    @XxlJob("genStar")
    @Transactional(rollbackFor = Exception.class)
    public void genStar() {

        try {
            LambdaQueryWrapper<SvWork> svWorkQueryWrapper = new LambdaQueryWrapper<>();
            svWorkQueryWrapper.eq(SvWork::getIsDel, IsDel.NORMAL.getCode());
            List<Long> workIds = svWorkService.list(svWorkQueryWrapper).stream().map(SvWork::getWorkId).collect(Collectors.toList());

            LambdaQueryWrapper<SvUser> svUserQueryWrapper = new LambdaQueryWrapper<>();
            svUserQueryWrapper.select(SvUser::getUserId);
            svUserQueryWrapper.eq(SvUser::getIsDel,IsDel.NORMAL.getCode());
            List<Long> userIds = svUserService.list(svUserQueryWrapper).stream().map(SvUser::getUserId).collect(Collectors.toList());


            int userNum = RandomUtil.randomInt(100,300);
            for (int i = 0; i < userNum; i++) {

                Long workId = RandomUtil.randomEle(workIds);

                LambdaQueryWrapper<SvWorkStar> svWorkStarQueryWrapper = new LambdaQueryWrapper<>();
                svWorkStarQueryWrapper.select(SvWorkStar::getWorkId);
                svWorkStarQueryWrapper.eq(SvWorkStar::getWorkId,workId);
                List<Long> likeUserIds = svWorkStarMapper.selectList(svWorkStarQueryWrapper).stream().map(SvWorkStar::getUserId).collect(Collectors.toList());

                List<Long> noStarUserIds = userIds.stream().filter(userId -> !likeUserIds.contains(userId)).collect(Collectors.toList());

                Long userId = RandomUtil.randomEle(noStarUserIds);
                svWorkService.star(workId,userId);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

    }


    @XxlJob("genLike")
    @Transactional(rollbackFor = Exception.class)
    public void genLike() {

        LambdaQueryWrapper<SvWork> svWorkQueryWrapper = new LambdaQueryWrapper<>();
        svWorkQueryWrapper.eq(SvWork::getIsDel, IsDel.NORMAL.getCode());
        List<Long> workIds = svWorkService.list(svWorkQueryWrapper).stream().map(SvWork::getWorkId).collect(Collectors.toList());

        LambdaQueryWrapper<SvUser> svUserQueryWrapper = new LambdaQueryWrapper<>();
        svUserQueryWrapper.select(SvUser::getUserId);
        svUserQueryWrapper.eq(SvUser::getIsDel,IsDel.NORMAL.getCode());
        List<Long> userIds = svUserService.list(svUserQueryWrapper).stream().map(SvUser::getUserId).collect(Collectors.toList());



        int userNum = RandomUtil.randomInt(30,100);
        for (int i = 0; i < userNum; i++) {

            Long workId = RandomUtil.randomEle(workIds);

            LambdaQueryWrapper<SvWorkLike> svWorkLikeQueryWrapper = new LambdaQueryWrapper<>();
            svWorkLikeQueryWrapper.select(SvWorkLike::getWorkId);
            svWorkLikeQueryWrapper.eq(SvWorkLike::getWorkId,workId);
            List<Long> likeUserIds = svWorkLikeMapper.selectList(svWorkLikeQueryWrapper).stream().map(SvWorkLike::getUserId).collect(Collectors.toList());

            List<Long> noLikeUserIds = userIds.stream().filter(userId -> !likeUserIds.contains(userId)).collect(Collectors.toList());

            Long userId = RandomUtil.randomEle(noLikeUserIds);
            svWorkService.like(workId,userId);
        }

    }

    @XxlJob("genUser")
    public void genUser() {
        ArrayList<SvUser> svUsers = new ArrayList<>();

        int userNum = RandomUtil.randomInt(300,500);

        for (int i = 0; i < userNum; i++) {

            String avatar = GenImage.getAvatar();
            String userName = GenUserName.generateNickname();

            List<SvUserAreaTreeVo> tree = svUserAreaService.tree();

            SvUser svUser = new SvUser();
            svUser.setUserName(userName);
            svUser.setAvatar(avatar);

            int areaProbability = RandomUtil.randomInt(1,100);

            List<Integer> popular = new ArrayList<>(Arrays.asList(44,31,11,32,33,37,35));

            List<Integer> unpopular = new ArrayList<>(Arrays.asList(15,63,54,64,65,62));


            List<SvUserAreaTreeVo> unpopularAreas = tree.stream()
                    .filter(svUserAreaTreeVo -> unpopular.contains(svUserAreaTreeVo.getAreaId()))
                    .collect(Collectors.toList());


            List<SvUserAreaTreeVo> popularAreas = tree.stream()
                    .filter(svUserAreaTreeVo -> popular.contains(svUserAreaTreeVo.getAreaId()))
                    .collect(Collectors.toList());

            List<SvUserAreaTreeVo> ordinaryAreas = tree.stream()
                    .filter(svUserAreaTreeVo -> !popular.contains(svUserAreaTreeVo.getAreaId()) && !unpopular.contains(svUserAreaTreeVo.getAreaId()))
                    .collect(Collectors.toList());

            if (areaProbability <= 60) {

                SvUserAreaTreeVo svUserAreaTreeVo = RandomUtil.randomEle(popularAreas);
                svUser.setPlaceProvinceId(svUserAreaTreeVo.getAreaId());
                if (ObjUtil.isNotEmpty(svUserAreaTreeVo.getChildren())) {
                    Integer areaId = RandomUtil.randomEle(svUserAreaTreeVo.getChildren()).getAreaId();
                    svUser.setPlaceCityId(areaId);
                }

            }


            if(areaProbability > 60 && areaProbability <= 98){

                SvUserAreaTreeVo svUserAreaTreeVo = RandomUtil.randomEle(ordinaryAreas);
                svUser.setPlaceProvinceId(svUserAreaTreeVo.getAreaId());
                if (ObjUtil.isNotEmpty(svUserAreaTreeVo.getChildren())) {
                    Integer areaId = RandomUtil.randomEle(svUserAreaTreeVo.getChildren()).getAreaId();
                    svUser.setPlaceCityId(areaId);
                }

            }

            if(areaProbability > 98){

                SvUserAreaTreeVo svUserAreaTreeVo = RandomUtil.randomEle(unpopularAreas);
                svUser.setPlaceProvinceId(svUserAreaTreeVo.getAreaId());
                if (ObjUtil.isNotEmpty(svUserAreaTreeVo.getChildren())) {
                    Integer areaId = RandomUtil.randomEle(svUserAreaTreeVo.getChildren()).getAreaId();
                    svUser.setPlaceCityId(areaId);
                }

            }


            int sexProbability = RandomUtil.randomInt(1, 100);

            if (sexProbability <= 50 ){
                svUser.setSex(0);
            }

            if (sexProbability > 50 && sexProbability <= 90) {
                svUser.setSex(1);
            }

            if (sexProbability >90){
                svUser.setSex(2);
            }

            svUsers.add(svUser);
        }
        svUserService.saveBatch(svUsers);
    }

    @Autowired
    private SvGenSettingService svGenSettingService;

    @XxlJob("genBrowse")
    @Transactional(rollbackFor = Exception.class)
    public void genBrowse() {

        LambdaQueryWrapper<SvUser> svUserQueryWrapper = new LambdaQueryWrapper<>();
        svUserQueryWrapper.select(SvUser::getUserId);
        svUserQueryWrapper.eq(SvUser::getIsDel,IsDel.NORMAL.getCode());
        List<Long> userIds = svUserService.list(svUserQueryWrapper).stream().map(SvUser::getUserId).collect(Collectors.toList());

        LambdaQueryWrapper<SvWork> svWorkQueryWrapper = new LambdaQueryWrapper<>();
        svWorkQueryWrapper.eq(SvWork::getIsDel, IsDel.NORMAL.getCode());
        List<Long> workIds = svWorkService.list(svWorkQueryWrapper).stream().map(SvWork::getWorkId).collect(Collectors.toList());

        try {
            List<Integer> visitPattern = new ArrayList<>(Arrays.asList(
                    400,   // 起始
                    1000,  // 高峰
                    300,   // 低谷
                    900,   // 高峰
                    400,   // 低谷
                    1100,  // 最高峰
                    200,   // 最低谷
                    800,   // 高峰
                    500,   // 中位
                    1000,  // 高峰
                    300,   // 低谷
                    950,   // 高峰
                    400,   // 低谷
                    850,   // 高峰
                    300,
                    700
            ));


            SvGenSetting svGenSetting = svGenSettingService.getById(1);
            Integer index = svGenSetting.getGenBrowseIndex();
            int browse = visitPattern.get(index) + RandomUtil.randomInt(-20, 20);

            for (int i = 1; i < browse; i++) {
                Long userId = RandomUtil.randomEle(userIds);
                Long workId = RandomUtil.randomEle(workIds);
                svWorkService.browseWork(userId,workId);
            }

            index ++;
            if (index > visitPattern.size() -1){
                index = 0;
            }

            svGenSetting.setGenBrowseIndex(index);
            svGenSettingService.updateById(svGenSetting);
        } catch (Exception e){
            log.error(e.getMessage(),e);
            throw new RuntimeException(e);
        }


    }


}
